Go Template

Introduction

ApplicationSet is able to use Go Text Template. To activate this feature, add goTemplate: true to your ApplicationSet manifest.

The Sprig function library (except for env, expandenv and getHostByName) is available in addition to the default Go Text Template functions.

An additional normalize function makes any string parameter usable as a valid DNS name by replacing invalid characters with hyphens and truncating at 253 characters. This is useful when making parameters safe for things like Application names.

Motivation

Go Template is the Go Standard for string templating. It is also more powerful than fasttemplate (the default templating engine) as it allows doing complex templating logic.

Limitations

Go templates are applied on a per-field basis, and only on string fields. Here are some examples of what is not possible with Go text templates:

  • Templating a boolean field.

    1. apiVersion: argoproj.io/v1alpha1
    2. kind: ApplicationSet
    3. spec:
    4. goTemplate: true
    5. template:
    6. spec:
    7. source:
    8. helm:
    9. useCredentials: "{{.useCredentials}}" # This field may NOT be templated, because it is a boolean field.
  • Templating an object field:

    1. apiVersion: argoproj.io/v1alpha1
    2. kind: ApplicationSet
    3. spec:
    4. goTemplate: true
    5. template:
    6. spec:
    7. syncPolicy: "{{.syncPolicy}}" # This field may NOT be templated, because it is an object field.
  • Using control keywords across fields:

    1. apiVersion: argoproj.io/v1alpha1
    2. kind: ApplicationSet
    3. spec:
    4. goTemplate: true
    5. template:
    6. spec:
    7. source:
    8. helm:
    9. parameters:
    10. # Each of these fields is evaluated as an independent template, so the first one will fail with an error.
    11. - name: "{{range .parameters}}"
    12. - name: "{{.name}}"
    13. value: "{{.value}}"
    14. - name: throw-away
    15. value: "{{end}}"

Migration guide

Globals

All your templates must replace parameters with GoTemplate Syntax:

Example: {{ some.value }} becomes {{ .some.value }}

Cluster Generators

By activating Go Templating, {{ .metadata }} becomes an object.

  • {{ metadata.labels.my-label }} becomes {{ index .metadata.labels "my-label" }}
  • {{ metadata.annotations.my/annotation }} becomes {{ index .metadata.annotations "my/annotation" }}

Git Generators

By activating Go Templating, {{ .path }} becomes an object. Therefore, some changes must be made to the Git generators’ templating:

  • {{ path }} becomes {{ .path.path }}
  • {{ path.basename }} becomes {{ .path.basename }}
  • {{ path.basenameNormalized }} becomes {{ .path.basenameNormalized }}
  • {{ path.filename }} becomes {{ .path.filename }}
  • {{ path.filenameNormalized }} becomes {{ .path.filenameNormalized }}
  • {{ path[n] }} becomes {{ index .path.segments n }}

Here is an example:

  1. apiVersion: argoproj.io/v1alpha1
  2. kind: ApplicationSet
  3. metadata:
  4. name: cluster-addons
  5. spec:
  6. generators:
  7. - git:
  8. repoURL: https://github.com/argoproj/argo-cd.git
  9. revision: HEAD
  10. directories:
  11. - path: applicationset/examples/git-generator-directory/cluster-addons/*
  12. template:
  13. metadata:
  14. name: '{{path.basename}}'
  15. spec:
  16. project: default
  17. source:
  18. repoURL: https://github.com/argoproj/argo-cd.git
  19. targetRevision: HEAD
  20. path: '{{path}}'
  21. destination:
  22. server: https://kubernetes.default.svc
  23. namespace: '{{path.basename}}'

becomes

  1. apiVersion: argoproj.io/v1alpha1
  2. kind: ApplicationSet
  3. metadata:
  4. name: cluster-addons
  5. spec:
  6. goTemplate: true
  7. generators:
  8. - git:
  9. repoURL: https://github.com/argoproj/argo-cd.git
  10. revision: HEAD
  11. directories:
  12. - path: applicationset/examples/git-generator-directory/cluster-addons/*
  13. template:
  14. metadata:
  15. name: '{{.path.basename}}'
  16. spec:
  17. project: default
  18. source:
  19. repoURL: https://github.com/argoproj/argo-cd.git
  20. targetRevision: HEAD
  21. path: '{{.path.path}}'
  22. destination:
  23. server: https://kubernetes.default.svc
  24. namespace: '{{.path.basename}}'

It is also possible to use Sprig functions to construct the path variables manually:

with goTemplate: falsewith goTemplate: truewith goTemplate: true + Sprig
{{path}}{{.path.path}}{{.path.path}}
{{path.basename}}{{.path.basename}}{{base .path.path}}
{{path.filename}}{{.path.filename}}{{.path.filename}}
{{path.basenameNormalized}}{{.path.basenameNormalized}}{{normalize .path.path}}
{{path.filenameNormalized}}{{.path.filenameNormalized}}{{normalize .path.filename}}
{{path[N]}}-{{index .path.segments N}}

Examples

Basic Go template usage

This example shows basic string parameter substitution.

  1. apiVersion: argoproj.io/v1alpha1
  2. kind: ApplicationSet
  3. metadata:
  4. name: guestbook
  5. spec:
  6. goTemplate: true
  7. generators:
  8. - list:
  9. elements:
  10. - cluster: engineering-dev
  11. url: https://1.2.3.4
  12. - cluster: engineering-prod
  13. url: https://2.4.6.8
  14. - cluster: finance-preprod
  15. url: https://9.8.7.6
  16. template:
  17. metadata:
  18. name: '{{.cluster}}-guestbook'
  19. spec:
  20. project: my-project
  21. source:
  22. repoURL: https://github.com/infra-team/cluster-deployments.git
  23. targetRevision: HEAD
  24. path: guestbook/{{.cluster}}
  25. destination:
  26. server: '{{.url}}'
  27. namespace: guestbook

Fallbacks for unset parameters

For some generators, a parameter of a certain name might not always be populated (for example, with the values generator or the git files generator). In these cases, you can use a Go template to provide a fallback value.

  1. apiVersion: argoproj.io/v1alpha1
  2. kind: ApplicationSet
  3. metadata:
  4. name: guestbook
  5. spec:
  6. goTemplate: true
  7. generators:
  8. - list:
  9. elements:
  10. - cluster: engineering-dev
  11. url: https://kubernetes.default.svc
  12. - cluster: engineering-prod
  13. url: https://kubernetes.default.svc
  14. nameSuffix: -my-name-suffix
  15. template:
  16. metadata:
  17. name: '{{.cluster}}{{default "" .nameSuffix}}'
  18. spec:
  19. project: default
  20. source:
  21. repoURL: https://github.com/argoproj/argo-cd.git
  22. targetRevision: HEAD
  23. path: applicationset/examples/list-generator/guestbook/{{.cluster}}
  24. destination:
  25. server: '{{.url}}'
  26. namespace: guestbook

This ApplicationSet will produce an Application called engineering-dev and another called engineering-prod-my-name-suffix.